package com.aliothservice.catfish.admin;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import javax.servlet.http.HttpServletRequest;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;

import com.aliothservice.catfish.SessionManager;
import com.aliothservice.catfish.admin.data.Admin;
import com.aliothservice.catfish.admin.data.AdminDataManager;
import com.aliothservice.catfish.admin.request.AddIdentityTemplateRequest;
import com.aliothservice.catfish.admin.request.AddNoteToVehicleBindingRequestRequest;
import com.aliothservice.catfish.admin.request.AddNoteToWarehouseBindingRequestRequest;
import com.aliothservice.catfish.admin.request.AddServiceTemplateRequest;
import com.aliothservice.catfish.admin.request.AdminGetVerificationCodeRequest;
import com.aliothservice.catfish.admin.request.AdminSignInRequest;
import com.aliothservice.catfish.admin.request.AdminUpdatePasswordRequest;
import com.aliothservice.catfish.admin.request.ApproveEnterprisePendingRequest;
import com.aliothservice.catfish.admin.request.ApproveIndividualPendingRequest;
import com.aliothservice.catfish.admin.request.ApproveProductPendingRequest;
import com.aliothservice.catfish.admin.request.ApproveVehiclePendingRequest;
import com.aliothservice.catfish.admin.request.ApproveWarehousePendingRequest;
import com.aliothservice.catfish.admin.request.ApproveWithdrawRequestRequest;
import com.aliothservice.catfish.admin.request.BindVehicleRequest;
import com.aliothservice.catfish.admin.request.BindWarehouseRequest;
import com.aliothservice.catfish.admin.request.DeleteIdentityTemplateRequest;
import com.aliothservice.catfish.admin.request.DeleteServiceTemplateRequest;
import com.aliothservice.catfish.admin.request.EnterprisePendingListRequest;
import com.aliothservice.catfish.admin.request.FilterIndividualUsersRequest;
import com.aliothservice.catfish.admin.request.HeartbeatMockupRequest;
import com.aliothservice.catfish.admin.request.HumidityMockupRequest;
import com.aliothservice.catfish.admin.request.IdentityTemplateListRequest;
import com.aliothservice.catfish.admin.request.IndividualPendingListRequest;
import com.aliothservice.catfish.admin.request.InfoUpdateForAdminConsoleRequest;
import com.aliothservice.catfish.admin.request.ListAppealRequestsRequest;
import com.aliothservice.catfish.admin.request.ListEnterpriseUsersRequest;
import com.aliothservice.catfish.admin.request.ListIndividualUsersRequest;
import com.aliothservice.catfish.admin.request.ListUsersRequest;
import com.aliothservice.catfish.admin.request.LocationMockupRequest;
import com.aliothservice.catfish.admin.request.MockupResultRequest;
import com.aliothservice.catfish.admin.request.ProcessedVehicleBindingRequestRequest;
import com.aliothservice.catfish.admin.request.ProcessedWarehouseBindingRequestRequest;
import com.aliothservice.catfish.admin.request.ProductPendingListRequest;
import com.aliothservice.catfish.admin.request.QueryIndividualUsersRequest;
import com.aliothservice.catfish.admin.request.QueryOnlineVehiclesRequest;
import com.aliothservice.catfish.admin.request.QueryOnlineWarehouseRequest;
import com.aliothservice.catfish.admin.request.QueryProductRequest;
import com.aliothservice.catfish.admin.request.QueryUserRequest;
import com.aliothservice.catfish.admin.request.QueryVehicleOrdersRequest;
import com.aliothservice.catfish.admin.request.QueryVehicleRequest;
import com.aliothservice.catfish.admin.request.QueryWarehouseRequest;
import com.aliothservice.catfish.admin.request.RejectEnterprisePendingRequest;
import com.aliothservice.catfish.admin.request.RejectIndividualPendingRequest;
import com.aliothservice.catfish.admin.request.RejectProductPendingRequest;
import com.aliothservice.catfish.admin.request.RejectVehiclePendingRequest;
import com.aliothservice.catfish.admin.request.RejectWarehousePendingRequest;
import com.aliothservice.catfish.admin.request.RejectWithdrawRequestRequest;
import com.aliothservice.catfish.admin.request.ResolveAppealRequest;
import com.aliothservice.catfish.admin.request.ResolvedAppealListRequest;
import com.aliothservice.catfish.admin.request.ServiceTemplateListRequest;
import com.aliothservice.catfish.admin.request.TemperatureMockupRequest;
import com.aliothservice.catfish.admin.request.VehicleBindingRequestListRequest;
import com.aliothservice.catfish.admin.request.VehiclePendingListRequest;
import com.aliothservice.catfish.admin.request.WarehouseBindingRequestListRequest;
import com.aliothservice.catfish.admin.request.WarehousePendingListRequest;
import com.aliothservice.catfish.admin.request.WithdrawRequestListRequest;
import com.aliothservice.catfish.device.request.VehicleLocationDocumentRequest;
import com.aliothservice.catfish.message.MessageController;
import com.aliothservice.catfish.message.data.Message;

public class AdminController {
	
	public Map<String, String> adminGetVerificationCode(AdminGetVerificationCodeRequest req) {
		Map<String, String> map = new HashMap<String, String>();

		// frequency check
		ValueOperations<String, Object> valueOp = redisTemplate.opsForValue();
		String frequencyMarker = (String)valueOp.get(req.getPhoneNumber() + AdminController.FREQUENCY_KEY_SUFFIX);
		if (null != frequencyMarker) {
			if (logger.isDebugEnabled()) {
				logger.debug("adminGetVerificationCode - " + req.getPhoneNumber() + " requests verification code too often, rejected.");
			}
			map.put("errorCode", "400");
			map.put("errorMessage", "request too often");
			return map;
		}
		valueOp.set(req.getPhoneNumber()+AdminController.FREQUENCY_KEY_SUFFIX, req.getPhoneNumber(), 60L, TimeUnit.SECONDS);
		
		String verString = (String)valueOp.get(req.getPhoneNumber() + AdminController.VERIFICATION_KEY_SUFFIX);
		if (null == verString) {
			// generate verification code
			String code = "1111";
			valueOp.set(req.getPhoneNumber()+AdminController.VERIFICATION_KEY_SUFFIX, code, 30L, TimeUnit.MINUTES);
			if (logger.isInfoEnabled()) {
				logger.info("getVerificationCode - code has been generated for " + req.getPhoneNumber());
			}
		} else {
			if (logger.isInfoEnabled()) {
				logger.info("adminGetVerificationCode - reuse existing code for " + req.getPhoneNumber());
			}
		}
	
		return map;
	}
	
	public Map<String, String> adminSignIn(AdminSignInRequest req) {
		Map<String, String> map = new HashMap<String, String>();
		
		// check verification code
		ValueOperations<String, Object> valueOp = redisTemplate.opsForValue();
		String verString = (String)valueOp.get(req.getPhoneNumber() + AdminController.VERIFICATION_KEY_SUFFIX);
		if ((null==verString) || (0!=verString.compareTo(req.getVerificationCode()))) {
			if (logger.isDebugEnabled()) {
				logger.debug("adminSignIn - verification code is invalid or expired");
			}
			map.put("errorCode", "300");
			map.put("errorMessage", "code expired or invalid code");
			return map;
		}

		// locate admin
		Admin admin = adminDataManager.findAdmin(req.getPhoneNumber());
		if (null == admin) {
			map.put("errorCode", "301");
			map.put("errorMessage", "user not found");
			return map;
		}
		
		// validate password
		if (0 != admin.getPassword().compareTo(req.getPassword())) {
			map.put("errorCode", "301");
			map.put("errorMessage", "validation failed");
			return map;
		}
		
		// send back token
		String token = sessionManager.createAdminToken(req.getPhoneNumber());
		map.put("token", token);
		
		return map;
	}
	
	public Map<String, String> adminUpdatePassword(AdminUpdatePasswordRequest req) {
		Map<String, String> map = new HashMap<String, String>();
		
		// validate token
		String loginName = (String)sessionManager.valueForAdminToken(req.getToken());
		if (null == loginName) {
			map.put("errorCode", "300");
			map.put("errorMessage", "token expired");
			return map;
		}
		
		// try update password
		if (!adminDataManager.updatePassword(loginName, req.getPassword())) {
			map.put("errorCode", "500");
			map.put("errorMessage", "failed to update password");
			return map;
		}
		
		// reset token expiration
		sessionManager.resetAdminTokenExpiration(loginName, req.getToken());
		
		return map;
	}
	
	public Map<String, String> rejectIndividualPending(RejectIndividualPendingRequest req) {
		Map<String, String> map = new HashMap<String, String>();
		
		// validate parameters
		if ((null==req.getPendingId()) || (null==req.getDescriptionOfReject())) {
			map.put("errorCode", "400");
			map.put("errorMessage", "missing parameters");
			return map;
		}
		
		// validate token
		String loginName = (String)sessionManager.valueForAdminToken(req.getToken());
		if (null == loginName) {
			map.put("errorCode", "300");
			map.put("errorMessage", "token expired");
			return map;
		}
		
		// update individual pending
		Message rejectMessage = adminDataManager.rejectIndividualPending(req.getPendingId(), req.getDescriptionOfReject());
		if (null == rejectMessage) {
			map.put("errorCode", "500");
			map.put("errorMessage", "failed to reject individual pending");
			return map;
		}
		
		//TODO send notification
		String phoneNumber = rejectMessage.getPayload();
		rejectMessage.setPayload("");
		messageController.postMessage(rejectMessage, phoneNumber);
		
		// reset token expiration
		sessionManager.resetAdminTokenExpiration(loginName, req.getToken());
		
		return map;
	}
	
	public Map<String, String> rejectEnterprisePending(RejectEnterprisePendingRequest req) {
		Map<String, String> map = new HashMap<String, String>();
		
		// validate parameters
		if ((null==req.getPendingId()) || (null==req.getDescriptionOfReject())) {
			map.put("errorCode", "400");
			map.put("errorMessage", "missing parameters");
			return map;
		}
		
		// validate token
		String loginName = (String)sessionManager.valueForAdminToken(req.getToken());
		if (null == loginName) {
			map.put("errorCode", "300");
			map.put("errorMessage", "token expired");
			return map;
		}
		
		// update enterprise pending
		Message rejectMessage = adminDataManager.rejectEnterprisePending(req.getPendingId(), req.getDescriptionOfReject());
		if (null == rejectMessage) {
			map.put("errorCode", "500");
			map.put("errorMessage", "failed to reject enterprise pending");
			return map;
		}
		
		//TODO send notification
		String phoneNumber = rejectMessage.getPayload();
		rejectMessage.setPayload("");
		messageController.postMessage(rejectMessage, phoneNumber);
		
		// reset token expiration
		sessionManager.resetAdminTokenExpiration(loginName, req.getToken());
		
		return map;
	}
	
	public Map<String, String> approveIndividualPending(ApproveIndividualPendingRequest req) {
		Map<String, String> map = new HashMap<String, String>();
		
		// validate parameters
		if (null == req.getPendingId()) {
			map.put("errorCode", "400");
			map.put("errorMessage", "missing parameters");
			return map;
		}
		
		// validate token
		String loginName = (String)sessionManager.valueForAdminToken(req.getToken());
		if (null == loginName) {
			map.put("errorCode", "300");
			map.put("errorMessage", "token expired");
			return map;
		}
		
		// update individual pending
		Message approvalMessage = adminDataManager.approveIndividualPending(req.getPendingId());
		if (null == approvalMessage) {
			map.put("errorCode", "500");
			map.put("errorMessage", "failed to approve individual pending");
			return map;
		}
		
		//TODO send notification
		String phoneNumber = approvalMessage.getPayload();
		approvalMessage.setPayload("");
		messageController.postMessage(approvalMessage, phoneNumber);
		
		// reset token expiration
		sessionManager.resetAdminTokenExpiration(loginName, req.getToken());
		
		return map;
	}
	
	public Map<String, String> approveEnterprisePending(ApproveEnterprisePendingRequest req) {
		Map<String, String> map = new HashMap<String, String>();
		
		// validate parameters
		if (null == req.getPendingId()) {
			map.put("errorCode", "400");
			map.put("errorMessage", "missing parameters");
			return map;
		}
		
		// validate token
		String loginName = (String)sessionManager.valueForAdminToken(req.getToken());
		if (null == loginName) {
			map.put("errorCode", "300");
			map.put("errorMessage", "token expired");
			return map;
		}
		
		// update enterprise pending
		Message approvalMessage = adminDataManager.approveEnterprisePending(req.getPendingId()); 
		if (null == approvalMessage) {
			map.put("errorCode", "500");
			map.put("errorMessage", "failed to approve enterprise pending");
			return map;
		}
		
		//TODO send notification
		String phoneNumber = approvalMessage.getPayload();
		approvalMessage.setPayload("");
		messageController.postMessage(approvalMessage, phoneNumber);
		
		// reset token expiration
		sessionManager.resetAdminTokenExpiration(loginName, req.getToken());
		
		return map;
	}
	
	public Map<String, String> addNoteToVehicleBindingRequest(AddNoteToVehicleBindingRequestRequest req) {
		Map<String, String> map = new HashMap<String, String>();
		
		// validate parameters
		if ((null==req.getReqId()) || (null==req.getNote())) {
			map.put("errorCode", "400");
			map.put("errorMessage", "missing parameters");
			return map;
		}
		
		// validate token
		String loginName = (String)sessionManager.valueForAdminToken(req.getToken());
		if (null == loginName) {
			map.put("errorCode", "300");
			map.put("errorMessage", "token expired");
			return map;
		}
		
		// perform addtion
		if (!adminDataManager.addNoteToVehicleBindingRequest(req)) {
			map.put("errorCode", "500");
			map.put("errorMessage", "failed to add");
			return map;
		}
		
		// reset token expiration
		sessionManager.resetAdminTokenExpiration(loginName, req.getToken());
		
		return map;
	}
	
	public Map<String, String> addNoteToWarehouseBindingRequest(AddNoteToWarehouseBindingRequestRequest req) {
		Map<String, String> map = new HashMap<String, String>();
		
		// validate parameters
		if ((null==req.getReqId()) || (null==req.getNote())) {
			map.put("errorCode", "400");
			map.put("errorMessage", "missing parameters");
			return map;
		}
		
		// validate token
		String loginName = (String)sessionManager.valueForAdminToken(req.getToken());
		if (null == loginName) {
			map.put("errorCode", "300");
			map.put("errorMessage", "token expired");
			return map;
		}
		
		// perform addtion
		if (!adminDataManager.addNoteToWarehouseBindingRequest(req)) {
			map.put("errorCode", "500");
			map.put("errorMessage", "failed to add");
			return map;
		}
		
		// reset token expiration
		sessionManager.resetAdminTokenExpiration(loginName, req.getToken());
		
		return map;
	}
	
	public Map<String, String> bindVehicle(BindVehicleRequest req) {
		Map<String, String> map = new HashMap<String, String>();
		
		// validate parameters
		if ((null==req.getVehicleId()) || (null==req.getDeviceSN())) {
			map.put("errorCode", "400");
			map.put("errorMessage", "missing parameters");
			return map;
		}
		
		// validate token
		String loginName = (String)sessionManager.valueForAdminToken(req.getToken());
		if (null == loginName) {
			map.put("errorCode", "300");
			map.put("errorMessage", "token expired");
			return map;
		}
		
		// perform binding
		if (!adminDataManager.bindVehicle(req)) {
			map.put("errorCode", "500");
			map.put("errorMessage", "failed to bind");
			return map;
		}
		
		// reset token expiration
		sessionManager.resetAdminTokenExpiration(loginName, req.getToken());
		
		return map;
	}
	
	public Map<String, String> bindWarehouse(BindWarehouseRequest req) {
		Map<String, String> map = new HashMap<String, String>();
		
		// validate parameters
		if ((null==req.getWarehouseId()) || (null==req.getDeviceSN())) {
			map.put("errorCode", "400");
			map.put("errorMessage", "missing parameters");
			return map;
		}
		
		// validate token
		String loginName = (String)sessionManager.valueForAdminToken(req.getToken());
		if (null == loginName) {
			map.put("errorCode", "300");
			map.put("errorMessage", "token expired");
			return map;
		}
		
		// perform binding
		if (!adminDataManager.bindWarehouse(req)) {
			map.put("errorCode", "500");
			map.put("errorMessage", "failed to bind");
			return map;
		}
		
		// reset token expiration
		sessionManager.resetAdminTokenExpiration(loginName, req.getToken());
		
		return map;
	}
	
	public Object queryVehicle(QueryVehicleRequest req) {
		Map<String, String> map = new HashMap<String, String>();
		
		// validate parameters
		if (null == req.getLicensePlate()) {
			map.put("errorCode", "400");
			map.put("errorMessage", "missing parameters");
			return map;
		}
		
		// validate token
		String loginName = (String)sessionManager.valueForAdminToken(req.getToken());
		if (null == loginName) {
			map.put("errorCode", "300");
			map.put("errorMessage", "token expired");
			return map;
		}
		
		// reset token expiration
		sessionManager.resetAdminTokenExpiration(loginName, req.getToken());
		
		return adminDataManager.queryVehicle(req);
	}
	
	public Map<String, String> addIdentityTemplate(AddIdentityTemplateRequest req) {
		Map<String, String> map = new HashMap<String, String>();
		
		// validate parameters
		if (null == req.getText()) {
			map.put("errorCode", "400");
			map.put("errorMessage", "missing parameters");
			return map;
		}
		
		// validate token
		String loginName = (String)sessionManager.valueForAdminToken(req.getToken());
		if (null == loginName) {
			map.put("errorCode", "300");
			map.put("errorMessage", "token expired");
			return map;
		}
		
		// perform addition
		adminDataManager.addIdentityTemplate(req);
		
		// reset token expiration
		sessionManager.resetAdminTokenExpiration(loginName, req.getToken());
		
		return map;
	}
	
	public Map<String, String> addServiceTemplate(AddServiceTemplateRequest req) {
		Map<String, String> map = new HashMap<String, String>();
		
		// validate parameters
		if (null == req.getText()) {
			map.put("errorCode", "400");
			map.put("errorMessage", "missing parameters");
			return map;
		}
		
		// validate token
		String loginName = (String)sessionManager.valueForAdminToken(req.getToken());
		if (null == loginName) {
			map.put("errorCode", "300");
			map.put("errorMessage", "token expired");
			return map;
		}
		
		// perform addition
		adminDataManager.addServiceTemplate(req);
		
		// reset token expiration
		sessionManager.resetAdminTokenExpiration(loginName, req.getToken());
		
		return map;
	}
	
	public Map<String, String> deleteIdentityTemplate(DeleteIdentityTemplateRequest req) {
		Map<String, String> map = new HashMap<String, String>();
		
		// validate parameters
		if (null == req.getTemplateId()) {
			map.put("errorCode", "400");
			map.put("errorMessage", "missing parameters");
			return map;
		}
		
		// validate token
		String loginName = (String)sessionManager.valueForAdminToken(req.getToken());
		if (null == loginName) {
			map.put("errorCode", "300");
			map.put("errorMessage", "token expired");
			return map;
		}
		
		// perform deletion
		if (!adminDataManager.deleteIdentityTemplate(req)) {
			map.put("errorCode", "500");
			map.put("errorMessage", "failed to delete");
			return map;
		}
		
		// reset token expiration
		sessionManager.resetAdminTokenExpiration(loginName, req.getToken());
		
		return map;
	}
	
	public Map<String, String> deleteServiceTemplate(DeleteServiceTemplateRequest req) {
		Map<String, String> map = new HashMap<String, String>();
		
		// validate parameters
		if (null == req.getTemplateId()) {
			map.put("errorCode", "400");
			map.put("errorMessage", "missing parameters");
			return map;
		}
		
		// validate token
		String loginName = (String)sessionManager.valueForAdminToken(req.getToken());
		if (null == loginName) {
			map.put("errorCode", "300");
			map.put("errorMessage", "token expired");
			return map;
		}
		
		// perform deletion
		if (!adminDataManager.deleteServiceTemplate(req)) {
			map.put("errorCode", "500");
			map.put("errorMessage", "failed to delete");
			return map;
		}
		
		// reset token expiration
		sessionManager.resetAdminTokenExpiration(loginName, req.getToken());
		
		return map;
	}
	
	public Object queryWarehouse(QueryWarehouseRequest req) {
		Map<String, Object> map = new HashMap<String, Object>();
		
		// validate parameters
		if (null == req.getName()) {
			map.put("errorCode", "400");
			map.put("errorMessage", "missing parameters");
			return map;
		}
		
		// validate token
		String loginName = (String)sessionManager.valueForAdminToken(req.getToken());
		if (null == loginName) {
			map.put("errorCode", "300");
			map.put("errorMessage", "token expired");
			return map;
		}
		
		// reset token expiration
		sessionManager.resetAdminTokenExpiration(loginName, req.getToken());
		
		return adminDataManager.queryWarehouse(req);
	}
	
	public Object queryProduct(QueryProductRequest req) {
		Map<String, Object> map = new HashMap<String, Object>();
		
		// validate parameters
		if (null == req.getTerm()) {
			map.put("errorCode", "400");
			map.put("errorMessage", "missing parameters");
			return map;
		}
		
		// validate token
		String loginName = (String)sessionManager.valueForAdminToken(req.getToken());
		if (null == loginName) {
			map.put("errorCode", "300");
			map.put("errorMessage", "token expired");
			return map;
		}
		
		// reset token expiration
		sessionManager.resetAdminTokenExpiration(loginName, req.getToken());
		
		// send back result
		return adminDataManager.queryProduct(req);
	}
	
	public Object queryUser(QueryUserRequest req) {
		Map<String, Object> map = new HashMap<String, Object>();
		
		// validate parameters
		if (null == req.getUserId()) {
			map.put("errorCode", "400");
			map.put("errorMessage", "missing parameters");
			return map;
		}
		
		// validate token
		String loginName = (String)sessionManager.valueForAdminToken(req.getToken());
		if (null == loginName) {
			map.put("errorCode", "300");
			map.put("errorMessage", "token expired");
			return map;
		}
		
		// perform query
		Map<String, Object> result = adminDataManager.queryUser(req);
		if (null == result) {
			map.put("errorCode", "500");
			map.put("errorMessage", "user not found");
			return map;
		}
		
		// reset token expiration
		sessionManager.resetAdminTokenExpiration(loginName, req.getToken());
		
		return result;
	}
	
	public Object queryOnlineVehicles(QueryOnlineVehiclesRequest req) {
		Map<String, Object> map = new HashMap<String, Object>();
		
		// validate token
		String loginName = (String)sessionManager.valueForAdminToken(req.getToken());
		if (null == loginName) {
			map.put("errorCode", "300");
			map.put("errorMessage", "token expired");
			return map;
		}

		// reset token expiration
		sessionManager.resetAdminTokenExpiration(loginName, req.getToken());
		
		// send back result
		return adminDataManager.queryOnlineVehicles(req);
	}
	
	public Object queryVehicleOrders(QueryVehicleOrdersRequest req) {
		Map<String, Object> map = new HashMap<String, Object>();
		
		// validate token
		String loginName = (String)sessionManager.valueForAdminToken(req.getToken());
		if (null == loginName) {
			map.put("errorCode", "300");
			map.put("errorMessage", "token expired");
			return map;
		}

		// reset token expiration
		sessionManager.resetAdminTokenExpiration(loginName, req.getToken());
		
		// send back result
		return adminDataManager.queryVehicleOrders(req);
	}
	
	public Object queryVehicleLocationDocument(VehicleLocationDocumentRequest req) {
		Map<String, Object> map = new HashMap<String, Object>();
		
		// validate token
		String loginName = (String)sessionManager.valueForAdminToken(req.getToken());
		if (null == loginName) {
			map.put("errorCode", "300");
			map.put("errorMessage", "token expired");
			return map;
		}
		
		// validate parameters
		if ((null==req.getOrderId()) || (null==req.getLongitude()) || (null==req.getLatitude()) || (null==req.getRadius())) {
			map.put("errorCode", "400");
			map.put("errorMessage", "missing parameters");
			return map;
		}
		
		// retrieve document
		Map<String, Object> documentMap = adminDataManager.queryVehicleLocationDocument(req);
		if (null == documentMap) {
			map.put("errorCode", "500");
			map.put("errorMessage", "location document not found");
			return map;
		}

		// reset token expiration
		sessionManager.resetAdminTokenExpiration(loginName, req.getToken());
		
		// send back result
		return documentMap;
	}
	
	public Object queryIndividualUsers(QueryIndividualUsersRequest req) {
		Map<String, Object> map = new HashMap<String, Object>();
		
		// validate parameters
		if (null == req.getPhoneNumber()) {
			map.put("errorCode", "400");
			map.put("errorMessage", "missing parameters");
			return map;
		}
		
		// validate token
		String loginName = (String)sessionManager.valueForAdminToken(req.getToken());
		if (null == loginName) {
			map.put("errorCode", "300");
			map.put("errorMessage", "token expired");
			return map;
		}
		
		// reset token expiration
		sessionManager.resetAdminTokenExpiration(loginName, req.getToken());
		
		// send back result
		return adminDataManager.queryIndividualUsers(req);
	}
	
	public Object queryEnterpriseUsers(QueryIndividualUsersRequest req) {
		Map<String, Object> map = new HashMap<String, Object>();
		
		// validate parameters
		if (null == req.getPhoneNumber()) {
			map.put("errorCode", "400");
			map.put("errorMessage", "missing parameters");
			return map;
		}
		
		// validate token
		String loginName = (String)sessionManager.valueForAdminToken(req.getToken());
		if (null == loginName) {
			map.put("errorCode", "300");
			map.put("errorMessage", "token expired");
			return map;
		}
		
		// reset token expiration
		sessionManager.resetAdminTokenExpiration(loginName, req.getToken());
		
		// send back result
		return adminDataManager.queryEnterpriseUsers(req);
	}
	
	public Object infoUpdateForAdminConsole(InfoUpdateForAdminConsoleRequest req) {
		Map<String, Object> map = new HashMap<String, Object>();
		
		// validate parameters
		if (null == req.getDate()) {
			map.put("errorCode", "400");
			map.put("errorMessage", "missing parameters");
			return map;
		}
		DateFormat fullFormatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS");
		Date date;
		try {
			date = fullFormatter.parse(req.getDate());
		} catch (ParseException e) {
			map.put("errorCode", "400");
			map.put("errorMessage", "missing parameters - invalid date");
			return map;
		}
		
		// validate token
		String loginName = (String)sessionManager.valueForAdminToken(req.getToken());
		if (null == loginName) {
			map.put("errorCode", "300");
			map.put("errorMessage", "token expired");
			return map;
		}
		
		// reset token expiration
		sessionManager.resetAdminTokenExpiration(loginName, req.getToken());
		
		return adminDataManager.infoUpdateForAdminConsole(date);
	}
	
	public Object queryOnlineWarehouse(QueryOnlineWarehouseRequest req) {
		Map<String, Object> map = new HashMap<String, Object>();
		
		// validate parameters
		if ((null==req.getLongitude()) || (null==req.getLatitude()) || (null==req.getRadius())) {
			map.put("errorCode", "400");
			map.put("errorMessage", "missing parameters");
			return map;
		}
		
		// validate token
		String loginName = (String)sessionManager.valueForAdminToken(req.getToken());
		if (null == loginName) {
			map.put("errorCode", "300");
			map.put("errorMessage", "token expired");
			return map;
		}
		
		// reset token expiration
		sessionManager.resetAdminTokenExpiration(loginName, req.getToken());
		
		return adminDataManager.queryOnlineWarehouse(req);
	}
	
	public Map<String, String> processedVehicleBindingRequest(ProcessedVehicleBindingRequestRequest req) {
		Map<String, String> map = new HashMap<String, String>();
		
		// validate parameters
		if (null == req.getReqId()) {
			map.put("errorCode", "400");
			map.put("errorMessage", "missing parameters");
			return map;
		}
		
		// validate token
		String loginName = (String)sessionManager.valueForAdminToken(req.getToken());
		if (null == loginName) {
			map.put("errorCode", "300");
			map.put("errorMessage", "token expired");
			return map;
		}
		
		// perform processing
		if (!adminDataManager.processedVehicleBindingRequest(req)) {
			map.put("errorCode", "500");
			map.put("errorMessage", "failed to process");
			return map;
		}
		
		// reset token expiration
		sessionManager.resetAdminTokenExpiration(loginName, req.getToken());
		
		return map;
	}
	
	public Map<String, String> resolveAppeal(ResolveAppealRequest req) {
		Map<String, String> map = new HashMap<String, String>();
		
		// validate parameters
		if ((null==req.getOrderId()) || (null==req.getBuyerAmount()) || (null==req.getSellerAmount()) || (null==req.getResultStatement())) {
			map.put("errorCode", "400");
			map.put("errorMessage", "missing parameters");
			return map;
		}
		
		// validate token
		String loginName = (String)sessionManager.valueForAdminToken(req.getToken());
		if (null == loginName) {
			map.put("errorCode", "300");
			map.put("errorMessage", "token expired");
			return map;
		}
		
		// perform processing
		if (!adminDataManager.resolveAppeal(req)) {
			map.put("errorCode", "500");
			map.put("errorMessage", "failed to process");
			return map;
		}
		
		// reset token expiration
		sessionManager.resetAdminTokenExpiration(loginName, req.getToken());
		
		return map;
	}
	
	public Map<String, String> processedWarehouseBindingRequest(ProcessedWarehouseBindingRequestRequest req) {
		Map<String, String> map = new HashMap<String, String>();
		
		// validate parameters
		if (null == req.getReqId()) {
			map.put("errorCode", "400");
			map.put("errorMessage", "missing parameters");
			return map;
		}
		
		// validate token
		String loginName = (String)sessionManager.valueForAdminToken(req.getToken());
		if (null == loginName) {
			map.put("errorCode", "300");
			map.put("errorMessage", "token expired");
			return map;
		}
		
		// perform processing
		if (!adminDataManager.processedWarehouseBindingRequest(req)) {
			map.put("errorCode", "500");
			map.put("errorMessage", "failed to process");
			return map;
		}
		
		// reset token expiration
		sessionManager.resetAdminTokenExpiration(loginName, req.getToken());
		
		return map;
	}
	
	public Object listUsers(ListUsersRequest req) {
		// validate token
		String loginName = (String)sessionManager.valueForAdminToken(req.getToken());
		if (null == loginName) {
			Map<String, String> map = new HashMap<String, String>();
			map.put("errorCode", "300");
			map.put("errorMessage", "token expired");
			return map;
		}
		
		// set up pageable
		int page;
		if (null != req.getPage()) {
			page = (req.getPage().intValue()>=0) ? req.getPage().intValue() : 0;
		} else {
			page = 0;
		}
		int size;
		if (null != req.getSize()) {
			size = (req.getSize().intValue()<100) ? req.getSize().intValue() : 100;
		} else {
			size = 100;
		}
		
		// reset token expiration
		sessionManager.resetAdminTokenExpiration(loginName, req.getToken());
		
		// send back result
		return adminDataManager.listUsers(new PageRequest(page, size));
	}
	
	public Object withdrawRequestList(WithdrawRequestListRequest req) {
		// validate token
		String loginName = (String)sessionManager.valueForAdminToken(req.getToken());
		if (null == loginName) {
			Map<String, String> map = new HashMap<String, String>();
			map.put("errorCode", "300");
			map.put("errorMessage", "token expired");
			return map;
		}
		
		// reset token expiration
		sessionManager.resetAdminTokenExpiration(loginName, req.getToken());
		
		// send back result
		return adminDataManager.withdrawRequestList();
	}
	
	public Object resolvedAppealList(ResolvedAppealListRequest req) {
		// validate token
		String loginName = (String)sessionManager.valueForAdminToken(req.getToken());
		if (null == loginName) {
			Map<String, String> map = new HashMap<String, String>();
			map.put("errorCode", "300");
			map.put("errorMessage", "token expired");
			return map;
		}
		
		// set up pageable
		int page;
		if (null != req.getPage()) {
			page = (req.getPage().intValue()>=0) ? req.getPage().intValue() : 0;
		} else {
			page = 0;
		}
		int size;
		if (null != req.getSize()) {
			size = (req.getSize().intValue()<100) ? req.getSize().intValue() : 100;
		} else {
			size = 100;
		}
		
		// reset token expiration
		sessionManager.resetAdminTokenExpiration(loginName, req.getToken());
		
		// send back result
		return adminDataManager.resolvedAppealList(new PageRequest(page, size));
	}
	
	public Object listIndividualUsers(ListIndividualUsersRequest req) {
		// validate token
		String loginName = (String)sessionManager.valueForAdminToken(req.getToken());
		if (null == loginName) {
			Map<String, String> map = new HashMap<String, String>();
			map.put("errorCode", "300");
			map.put("errorMessage", "token expired");
			return map;
		}
		
		// set up pageable
		int page;
		if (null != req.getPage()) {
			page = (req.getPage().intValue()>=0) ? req.getPage().intValue() : 0;
		} else {
			page = 0;
		}
		int size;
		if (null != req.getSize()) {
			size = (req.getSize().intValue()<100) ? req.getSize().intValue() : 100;
		} else {
			size = 100;
		}
		
		// reset token expiration
		sessionManager.resetAdminTokenExpiration(loginName, req.getToken());
		
		// send back result
		return adminDataManager.listIndividualUsers(new PageRequest(page, size));
	}
	
	public Object filterIndividualUsers(FilterIndividualUsersRequest req) {
		// validate token
		String loginName = (String)sessionManager.valueForAdminToken(req.getToken());
		if (null == loginName) {
			Map<String, String> map = new HashMap<String, String>();
			map.put("errorCode", "300");
			map.put("errorMessage", "token expired");
			return map;
		}
		
		// reset token expiration
		sessionManager.resetAdminTokenExpiration(loginName, req.getToken());
		
		// send back result
		return adminDataManager.filterIndividualUsers(req);
	}
	
	public Object filterEnterpriseUsers(FilterIndividualUsersRequest req) {
		// validate token
		String loginName = (String)sessionManager.valueForAdminToken(req.getToken());
		if (null == loginName) {
			Map<String, String> map = new HashMap<String, String>();
			map.put("errorCode", "300");
			map.put("errorMessage", "token expired");
			return map;
		}
		
		// reset token expiration
		sessionManager.resetAdminTokenExpiration(loginName, req.getToken());
		
		// send back result
		return adminDataManager.filterEnterpriseUsers(req);
	}
	
	public Object filterVehicles(FilterIndividualUsersRequest req) {
		// validate token
		String loginName = (String)sessionManager.valueForAdminToken(req.getToken());
		if (null == loginName) {
			Map<String, String> map = new HashMap<String, String>();
			map.put("errorCode", "300");
			map.put("errorMessage", "token expired");
			return map;
		}
		
		// reset token expiration
		sessionManager.resetAdminTokenExpiration(loginName, req.getToken());
		
		// send back result
		return adminDataManager.filterVehicles(req);
	}
	
	public Object filterWarehouses(FilterIndividualUsersRequest req) {
		// validate token
		String loginName = (String)sessionManager.valueForAdminToken(req.getToken());
		if (null == loginName) {
			Map<String, String> map = new HashMap<String, String>();
			map.put("errorCode", "300");
			map.put("errorMessage", "token expired");
			return map;
		}
		
		// reset token expiration
		sessionManager.resetAdminTokenExpiration(loginName, req.getToken());
		
		// send back result
		return adminDataManager.filterWarehouses(req);
	}
	
	public Object filterProducts(FilterIndividualUsersRequest req) {
		// validate token
		String loginName = (String)sessionManager.valueForAdminToken(req.getToken());
		if (null == loginName) {
			Map<String, String> map = new HashMap<String, String>();
			map.put("errorCode", "300");
			map.put("errorMessage", "token expired");
			return map;
		}
		
		// reset token expiration
		sessionManager.resetAdminTokenExpiration(loginName, req.getToken());
		
		// send back result
		return adminDataManager.filterProducts(req);
	}
	
	public Object listEnterpriseUsers(ListEnterpriseUsersRequest req) {
		// validate token
		String loginName = (String)sessionManager.valueForAdminToken(req.getToken());
		if (null == loginName) {
			Map<String, String> map = new HashMap<String, String>();
			map.put("errorCode", "300");
			map.put("errorMessage", "token expired");
			return map;
		}
		
		// set up pageable
		int page;
		if (null != req.getPage()) {
			page = (req.getPage().intValue()>=0) ? req.getPage().intValue() : 0;
		} else {
			page = 0;
		}
		int size;
		if (null != req.getSize()) {
			size = (req.getSize().intValue()<100) ? req.getSize().intValue() : 100;
		} else {
			size = 100;
		}
		
		// reset token expiration
		sessionManager.resetAdminTokenExpiration(loginName, req.getToken());
		
		// send back result
		return adminDataManager.listEnterpriseUsers(new PageRequest(page, size));
	}
	
	public Object listAppealRequests(ListAppealRequestsRequest req) {
		// validate token
		String loginName = (String)sessionManager.valueForAdminToken(req.getToken());
		if (null == loginName) {
			Map<String, String> map = new HashMap<String, String>();
			map.put("errorCode", "300");
			map.put("errorMessage", "token expired");
			return map;
		}
		
		// reset token expiration
		sessionManager.resetAdminTokenExpiration(loginName, req.getToken());
		
		// send back result
		return adminDataManager.listAppealRequests();
	}
	
	public Object identityTemplateList(IdentityTemplateListRequest req) {
		// validate token
		String loginName = (String)sessionManager.valueForAdminToken(req.getToken());
		if (null == loginName) {
			Map<String, String> map = new HashMap<String, String>();
			map.put("errorCode", "300");
			map.put("errorMessage", "token expired");
			return map;
		}
		
		// reset token expiration
		sessionManager.resetAdminTokenExpiration(loginName, req.getToken());

		// send back result
		return adminDataManager.identityTemplateList();
	}
	
	public Object serviceTemplateList(ServiceTemplateListRequest req) {
		// validate token
		String loginName = (String)sessionManager.valueForAdminToken(req.getToken());
		if (null == loginName) {
			Map<String, String> map = new HashMap<String, String>();
			map.put("errorCode", "300");
			map.put("errorMessage", "token expired");
			return map;
		}
		
		// reset token expiration
		sessionManager.resetAdminTokenExpiration(loginName, req.getToken());

		// send back result
		return adminDataManager.serviceTemplateList();
	}
	
	public Object individualPendingList(IndividualPendingListRequest req) {
		// validate token
		String loginName = (String)sessionManager.valueForAdminToken(req.getToken());
		if (null == loginName) {
			Map<String, String> map = new HashMap<String, String>();
			map.put("errorCode", "300");
			map.put("errorMessage", "token expired");
			return map;
		}
		
		// set up pageable
		int page;
		if (null != req.getPage()) {
			page = (req.getPage().intValue()>=0) ? req.getPage().intValue() : 0;
		} else {
			page = 0;
		}
		int size;
		if (null != req.getSize()) {
			size = (req.getSize().intValue()<100) ? req.getSize().intValue() : 100;
		} else {
			size = 100;
		}
		
		// reset token expiration
		sessionManager.resetAdminTokenExpiration(loginName, req.getToken());
		
		// send back result
		return adminDataManager.individualPendingList(new PageRequest(page, size));
	}
	
	public Object vehicleBindingRequestList(VehicleBindingRequestListRequest req) {
		// validate token
		String loginName = (String)sessionManager.valueForAdminToken(req.getToken());
		if (null == loginName) {
			Map<String, String> map = new HashMap<String, String>();
			map.put("errorCode", "300");
			map.put("errorMessage", "token expired");
			return map;
		}
		
		// set up pageable
		int page;
		if (null != req.getPage()) {
			page = (req.getPage().intValue()>=0) ? req.getPage().intValue() : 0;
		} else {
			page = 0;
		}
		int size;
		if (null != req.getSize()) {
			size = (req.getSize().intValue()<100) ? req.getSize().intValue() : 100;
		} else {
			size = 100;
		}
		
		// reset token expiration
		sessionManager.resetAdminTokenExpiration(loginName, req.getToken());

		// send back result
		return adminDataManager.vehicleBindingRequestList(new PageRequest(page, size));
	}
	
	public Object warehouseBindingRequestList(WarehouseBindingRequestListRequest req) {
		// validate token
		String loginName = (String)sessionManager.valueForAdminToken(req.getToken());
		if (null == loginName) {
			Map<String, String> map = new HashMap<String, String>();
			map.put("errorCode", "300");
			map.put("errorMessage", "token expired");
			return map;
		}
		
		// set up pageable
		int page;
		if (null != req.getPage()) {
			page = (req.getPage().intValue()>=0) ? req.getPage().intValue() : 0;
		} else {
			page = 0;
		}
		int size;
		if (null != req.getSize()) {
			size = (req.getSize().intValue()<100) ? req.getSize().intValue() : 100;
		} else {
			size = 100;
		}
		
		// reset token expiration
		sessionManager.resetAdminTokenExpiration(loginName, req.getToken());

		// send back result
		return adminDataManager.warehouseBindingRequestList(new PageRequest(page, size));
	}
	
	public Object enterprisePendingList(EnterprisePendingListRequest req) {
		// validate token
		String loginName = (String)sessionManager.valueForAdminToken(req.getToken());
		if (null == loginName) {
			Map<String, String> map = new HashMap<String, String>();
			map.put("errorCode", "300");
			map.put("errorMessage", "token expired");
			return map;
		}
		
		// set up pageable
		int page;
		if (null != req.getPage()) {
			page = (req.getPage().intValue()>=0) ? req.getPage().intValue() : 0;
		} else {
			page = 0;
		}
		int size;
		if (null != req.getSize()) {
			size = (req.getSize().intValue()<100) ? req.getSize().intValue() : 100;
		} else {
			size = 100;
		}

		// reset token expiration
		sessionManager.resetAdminTokenExpiration(loginName, req.getToken());
		
		// send back result
		return adminDataManager.enterprisePendingList(new PageRequest(page, size));
	}
	
	public Object vehiclePendingList(VehiclePendingListRequest req) {
		// validate token
		String loginName = (String)sessionManager.valueForAdminToken(req.getToken());
		if (null == loginName) {
			Map<String, String> map = new HashMap<String, String>();
			map.put("errorCode", "300");
			map.put("errorMessage", "token expired");
			return map;
		}
		
		// set up pageable
		int page;
		if (null != req.getPage()) {
			page = (req.getPage().intValue()>=0) ? req.getPage().intValue() : 0;
		} else {
			page = 0;
		}
		int size;
		if (null != req.getSize()) {
			size = (req.getSize().intValue()<100) ? req.getSize().intValue() : 100;
		} else {
			size = 100;
		}
		
		// reset token expiration
		sessionManager.resetAdminTokenExpiration(loginName, req.getToken());
		
		// send back result
		return adminDataManager.vehiclePendingList(new PageRequest(page, size));
	}
	
	public Object warehousePendingList(WarehousePendingListRequest req) {
		// validate token
		String loginName = (String)sessionManager.valueForAdminToken(req.getToken());
		if (null == loginName) {
			Map<String, String> map = new HashMap<String, String>();
			map.put("errorCode", "300");
			map.put("errorMessage", "token expired");
			return map;
		}
		
		// set up pageable
		int page;
		if (null != req.getPage()) {
			page = (req.getPage().intValue()>=0) ? req.getPage().intValue() : 0;
		} else {
			page = 0;
		}
		int size;
		if (null != req.getSize()) {
			size = (req.getSize().intValue()<100) ? req.getSize().intValue() : 100;
		} else {
			size = 100;
		}
		
		// reset token expiration
		sessionManager.resetAdminTokenExpiration(loginName, req.getToken());
		
		// send back result
		return adminDataManager.warehousePendingList(new PageRequest(page, size));
	}
	
	public Object productPendingList(ProductPendingListRequest req) {
		// validate token
		String loginName = (String)sessionManager.valueForAdminToken(req.getToken());
		if (null == loginName) {
			Map<String, String> map = new HashMap<String, String>();
			map.put("errorCode", "300");
			map.put("errorMessage", "token expired");
			return map;
		}
		
		// set up pageable
		int page;
		if (null != req.getPage()) {
			page = (req.getPage().intValue()>=0) ? req.getPage().intValue() : 0;
		} else {
			page = 0;
		}
		int size;
		if (null != req.getSize()) {
			size = (req.getSize().intValue()<100) ? req.getSize().intValue() : 100;
		} else {
			size = 100;
		}
		
		// reset token expiration
		sessionManager.resetAdminTokenExpiration(loginName, req.getToken());
		
		// send back result
		return adminDataManager.productPendingList(new PageRequest(page, size));
	}
	
	public Map<String, String> rejectWithdrawRequest(RejectWithdrawRequestRequest req) {
		Map<String, String> map = new HashMap<String, String>();
		
		// validate parameters
		if ((null==req.getRequestId()) || (null==req.getDescriptionOfReject())) {
			map.put("errorCode", "400");
			map.put("errorMessage", "missing parameters");
			return map;
		}
		
		// validate token
		String loginName = (String)sessionManager.valueForAdminToken(req.getToken());
		if (null == loginName) {
			map.put("errorCode", "300");
			map.put("errorMessage", "token expired");
			return map;
		}
		
		// perform rejection
		Message rejectMessage = adminDataManager.rejectWithdrawRequest(req.getRequestId(), req.getDescriptionOfReject());
		if (null == rejectMessage) {
			map.put("errorCode", "500");
			map.put("errorMessage", "failed to reject");
			return map;
		}
		
		// TODO send notification
		String phoneNumber = rejectMessage.getPayload();
		rejectMessage.setPayload("");
		messageController.postMessage(rejectMessage, phoneNumber);
		
		// reset token expiration
		sessionManager.resetAdminTokenExpiration(loginName, req.getToken());
		
		return map;
	}
	
	public Map<String, String> rejectVehiclePending(RejectVehiclePendingRequest req) {
		Map<String, String> map = new HashMap<String, String>();
		
		// validate parameters
		if ((null==req.getPendingId()) || (null==req.getDescriptionOfReject())) {
			map.put("errorCode", "400");
			map.put("errorMessage", "missing parameters");
			return map;
		}
		
		// validate token
		String loginName = (String)sessionManager.valueForAdminToken(req.getToken());
		if (null == loginName) {
			map.put("errorCode", "300");
			map.put("errorMessage", "token expired");
			return map;
		}
		
		// perform rejection
		Message rejectMessage = adminDataManager.rejectVehiclePending(req.getPendingId(), req.getDescriptionOfReject());
		if (null == rejectMessage) {
			map.put("errorCode", "500");
			map.put("errorMessage", "failed to reject vehicle pending");
			return map;
		}
		
		// TODO send notification
		String phoneNumber = rejectMessage.getPayload();
		rejectMessage.setPayload("");
		messageController.postMessage(rejectMessage, phoneNumber);
		
		// reset token expiration
		sessionManager.resetAdminTokenExpiration(loginName, req.getToken());
		
		return map;
	}
	
	public Map<String, String> rejectWarehousePending(RejectWarehousePendingRequest req) {
		Map<String, String> map = new HashMap<String, String>();
		
		// validate parameters
		if ((null==req.getPendingId()) || (null==req.getDescriptionOfReject())) {
			map.put("errorCode", "400");
			map.put("errorMessage", "missing parameters");
			return map;
		}
		
		// validate token
		String loginName = (String)sessionManager.valueForAdminToken(req.getToken());
		if (null == loginName) {
			map.put("errorCode", "300");
			map.put("errorMessage", "token expired");
			return map;
		}
		
		// perform reject
		Message rejectMessage = adminDataManager.rejectWarehousePending(req.getPendingId(), req.getDescriptionOfReject());
		if (null == rejectMessage) {
			map.put("errorCode", "500");
			map.put("errorMessage", "failed to reject");
			return map;
		}
		
		// TODO send notification
		String phoneNumber = rejectMessage.getPayload();
		rejectMessage.setPayload("");
		messageController.postMessage(rejectMessage, phoneNumber);
		
		// reset token expiration
		sessionManager.resetAdminTokenExpiration(loginName, req.getToken());
		
		return map;
	}
	
	public Map<String, String> rejectProductPending(RejectProductPendingRequest req) {
		Map<String, String> map = new HashMap<String, String>();
		
		// validate parameters
		if ((null==req.getPendingId()) || (null==req.getDescriptionOfReject())) {
			map.put("errorCode", "400");
			map.put("errorMessage", "missing parameters");
			return map;
		}
		
		// validate token
		String loginName = (String)sessionManager.valueForAdminToken(req.getToken());
		if (null == loginName) {
			map.put("errorCode", "300");
			map.put("errorMessage", "token expired");
			return map;
		}
		
		// perform reject
		Message rejectMessage = adminDataManager.rejectProductPending(req.getPendingId(), req.getDescriptionOfReject());
		if (null == rejectMessage) {
			map.put("errorCode", "500");
			map.put("errorMessage", "failed to reject");
			return map;
		}
		
		// TODO send notification
		String phoneNumber = rejectMessage.getPayload();
		rejectMessage.setPayload("");
		messageController.postMessage(rejectMessage, phoneNumber);
		
		// reset token expiration
		sessionManager.resetAdminTokenExpiration(loginName, req.getToken());
		
		return map;
	}
	
	public Map<String, String> approveWithdrawRequest(ApproveWithdrawRequestRequest req) {
		Map<String, String> map = new HashMap<String, String>();
		
		// validate parameters
		if (null == req.getRequestId()) {
			map.put("errorCode", "400");
			map.put("errorMessage", "missing parameters");
			return map;
		}
		
		// validate token
		String loginName = (String)sessionManager.valueForAdminToken(req.getToken());
		if (null == loginName) {
			map.put("errorCode", "300");
			map.put("errorMessage", "token expired");
			return map;
		}
		
		// perform approval
		if (!adminDataManager.approveWithdrawRequest(req.getRequestId())) {
			map.put("errorCode", "500");
			map.put("errorMessage", "failed to approve");
			return map;
		}
		
		// reset token expiration
		sessionManager.resetAdminTokenExpiration(loginName, req.getToken());
		
		return map;
	}
	
	public Map<String, String> approveVehiclePending(ApproveVehiclePendingRequest req) {
		Map<String, String> map = new HashMap<String, String>();
		
		// validate parameters
		if ((null==req.getPendingId()) || (null==req.getExpiredBy())) {
			map.put("errorCode", "400");
			map.put("errorMessage", "missing parameters");
			return map;
		}
		DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
		Date expiredBy = null;
		try {
			expiredBy = formatter.parse(req.getExpiredBy());
		} catch (ParseException e) {
			map.put("errorCode", "400");
			map.put("errorMessage", "missing parameters");
			return map;
		}
		
		// validate token
		String loginName = (String)sessionManager.valueForAdminToken(req.getToken());
		if (null == loginName) {
			map.put("errorCode", "300");
			map.put("errorMessage", "token expired");
			return map;
		}
		
		// perform approval
		Message approvalMessage = adminDataManager.approveVehiclePending(req.getPendingId(), expiredBy);
		if (null == approvalMessage) {
			map.put("errorCode", "500");
			map.put("errorMessage", "failed to approve vehicle pending");
			return map;
		}
		
		// TODO send notification
		String phoneNumber = approvalMessage.getPayload();
		approvalMessage.setPayload("");
		messageController.postMessage(approvalMessage, phoneNumber);
		
		// reset token expiration
		sessionManager.resetAdminTokenExpiration(loginName, req.getToken());		
		
		return map;
	}
	
	public Map<String, String> approveWarehousePending(ApproveWarehousePendingRequest req) {
		Map<String, String> map = new HashMap<String, String>();
		
		// validate parameters
		if ((null==req.getPendingId()) || (null==req.getLongitude()) || (null==req.getLatitude())) {
			map.put("errorCode", "400");
			map.put("errorMessage", "missing parameters");
			return map;
		}
		if (Math.abs(req.getLatitude().doubleValue()) > 90) {
			map.put("errorCode", "400");
			map.put("errorMessage", "missing parameters - invalid latitude");
			return map;
		}
		
		// validate token
		String loginName = (String)sessionManager.valueForAdminToken(req.getToken());
		if (null == loginName) {
			map.put("errorCode", "300");
			map.put("errorMessage", "token expired");
			return map;
		}
		
		// perform approval
		Message approvalMessage = adminDataManager.approveWarehousePending(req.getPendingId(), req.getLongitude(), req.getLatitude());
		if (null == approvalMessage) {
			map.put("errorCode", "500");
			map.put("errorMessage", "failed to approve");
			return map;
		}
		
		// TODO send notification
		String phoneNumber = approvalMessage.getPayload();
		approvalMessage.setPayload("");
		messageController.postMessage(approvalMessage, phoneNumber);
		
		// reset token expiration
		sessionManager.resetAdminTokenExpiration(loginName, req.getToken());		
		
		return map;
	}
	
	public Map<String, String> approveProductPending(ApproveProductPendingRequest req) {
		Map<String, String> map = new HashMap<String, String>();
		
		// validate parameters
		if (null == req.getPendingId()) {
			map.put("errorCode", "400");
			map.put("errorMessage", "missing parameters");
			return map;
		}
		
		// validate token
		String loginName = (String)sessionManager.valueForAdminToken(req.getToken());
		if (null == loginName) {
			map.put("errorCode", "300");
			map.put("errorMessage", "token expired");
			return map;
		}
		
		// perform approval
		Message approvalMessage = adminDataManager.approveProductPending(req.getPendingId());
		if (null == approvalMessage) {
			map.put("errorCode", "500");
			map.put("errorMessage", "failed to approve");
			return map;
		}
		
		
		// TODO send notification
		String phoneNumber = approvalMessage.getPayload();
		approvalMessage.setPayload("");
		messageController.postMessage(approvalMessage, phoneNumber);
		
		// reset token expiration
		sessionManager.resetAdminTokenExpiration(loginName, req.getToken());		
		
		return map;
	}
	
	public Map<String, String> heartbeatMockup(HeartbeatMockupRequest req) {
		Map<String, String> map = new HashMap<String, String>();
		
		// validate parameters
		if (null == req.getDeviceSN()) {
			map.put("errorCode", "400");
			map.put("errorMessage", "missing parameters");
			return map;
		}
		if (req.getDeviceSN().length() != 8) {
			map.put("errorCode", "400");
			map.put("errorMessage", "missing parameters - invalid sn length");
			return map;
		}
		
		// validate token
		String loginName = (String)sessionManager.valueForAdminToken(req.getToken());
		if (null == loginName) {
			map.put("errorCode", "300");
			map.put("errorMessage", "token expired");
			return map;
		}
		
		String receipt = adminDataManager.heartbeatMockup(req);
		map.put("receipt", receipt);
		
		return map;
		
	}
	
	public Map<String, String> locationMockup(LocationMockupRequest req) {
		Map<String, String> map = new HashMap<String, String>();
		
		// validate parameters
		if ((null==req.getDeviceSN()) || (null==req.getLongitude()) || (null==req.getLatitude())) {
			map.put("errorCode", "400");
			map.put("errorMessage", "missing parameters");
			return map;
		}
		if (req.getDeviceSN().length() != 8) {
			map.put("errorCode", "400");
			map.put("errorMessage", "missing parameters - invalid sn length");
			return map;
		}
		
		// validate token
		String loginName = (String)sessionManager.valueForAdminToken(req.getToken());
		if (null == loginName) {
			map.put("errorCode", "300");
			map.put("errorMessage", "token expired");
			return map;
		}
		
		String receipt = adminDataManager.locationMockup(req);
		map.put("receipt", receipt);
		
		return map;
	}
	
	public Map<String, String> temperatureMockup(TemperatureMockupRequest req) {
		Map<String, String> map = new HashMap<String, String>();
		
		// validate parameters
		if ((null==req.getDeviceSN()) || (null==req.getTemperature()) || (null==req.getLongitude()) || (null==req.getLatitude())) {
			map.put("errorCode", "400");
			map.put("errorMessage", "missing parameters");
			return map;
		}
		if (req.getDeviceSN().length() != 8) {
			map.put("errorCode", "400");
			map.put("errorMessage", "missing parameters - invalid sn length");
			return map;
		}
		
		// validate token
		String loginName = (String)sessionManager.valueForAdminToken(req.getToken());
		if (null == loginName) {
			map.put("errorCode", "300");
			map.put("errorMessage", "token expired");
			return map;
		}
		
		String receipt = adminDataManager.temperatureMockup(req);
		map.put("receipt", receipt);
		
		return map;
	}
	
	public Map<String, String> humidityMockup(HumidityMockupRequest req) {
		Map<String, String> map = new HashMap<String, String>();
		
		// validate parameters
		if ((null==req.getDeviceSN()) || (null==req.getHumidity()) || (null==req.getLongitude()) || (null==req.getLatitude())) {
			map.put("errorCode", "400");
			map.put("errorMessage", "missing parameters");
			return map;
		}
		if (req.getDeviceSN().length() != 8) {
			map.put("errorCode", "400");
			map.put("errorMessage", "missing parameters - invalid sn length");
			return map;
		}
		
		// validate token
		String loginName = (String)sessionManager.valueForAdminToken(req.getToken());
		if (null == loginName) {
			map.put("errorCode", "300");
			map.put("errorMessage", "token expired");
			return map;
		}
		
		String receipt = adminDataManager.humidityMockup(req);
		map.put("receipt", receipt);
		
		return map;
	}
	
	public Map<String, String> mockupResult(MockupResultRequest req) {
		Map<String, String> map = new HashMap<String, String>();
		
		// validate parameters
		if (null == req.getReceipt()) {
			map.put("errorCode", "400");
			map.put("errorMessage", "missing parameters");
			return map;
		}
		
		// validate token
		String loginName = (String)sessionManager.valueForAdminToken(req.getToken());
		if (null == loginName) {
			map.put("errorCode", "300");
			map.put("errorMessage", "token expired");
			return map;
		}
		
		String trace = adminDataManager.mockupResult(req);
		if (null != trace) {
			map.put("operationTrace", trace);
		}
		
		return map;
	}
			
	public String clientIp(HttpServletRequest httpReq) {
		String ip = httpReq.getHeader("X-Forwarded-For");
		if ((null==ip) || (0==ip.length()) || "unknown".equalsIgnoreCase(ip)) {
			ip = httpReq.getHeader("Proxy-Client-IP");
			if ((null==ip) || (0==ip.length()) || "unknown".equalsIgnoreCase(ip)) {
				ip = httpReq.getHeader("WL-Proxy-Client-IP");
			}
			if ((null==ip) || (0==ip.length()) || "unknown".equalsIgnoreCase(ip)) {
				ip = httpReq.getHeader("HTTP_CLIENT_IP");
			}
			if ((null==ip) || (0==ip.length()) || "unknown".equalsIgnoreCase(ip)) {
				ip = httpReq.getHeader("HTTP_X_FORWARDED_FOR");
			}
			if ((null==ip) || (0==ip.length()) || "unknown".equalsIgnoreCase(ip)) {
				ip = httpReq.getRemoteAddr();
			}
		} else {
			String[] ips = ip.split(",");
			for (int index=0; index<ips.length; index++) {
				String ipString = ips[index];
				if (!("unknown".equalsIgnoreCase(ipString))) {
					ip = ipString;
					break;
				}
			}
		}
		
		return ip;
	}
		
	@Autowired
	private AdminDataManager adminDataManager;
	
	@Autowired
	private MessageController messageController;
	
	@Autowired
	private SessionManager sessionManager;
	
	@Autowired
	private RedisTemplate<String, Object> redisTemplate;
	
	private static final Logger logger = LoggerFactory.getLogger(AdminController.class);

	private static final String FREQUENCY_KEY_SUFFIX = "_FREQ_KEY";
	private static final String VERIFICATION_KEY_SUFFIX = "_VER_KEY";
}
